﻿#pragma once

#include <memory>
#include <vector>

#include "../Utils/HCNMath.h"

#include "TextHolder.h"

class CompoundTag;
class Tag;
class C_BlockLegacy;
class C_BlockSource;
class C_Block;
class C_Entity;
class C_ItemStack;
class C_ScreenContext;
class C_ItemRenderer;
class C_ClientInstance;
class MinecraftGame;

class C_BaseActorRenderContext {
private:
	[[maybe_unused]] uint8_t pad_0x0[0x60]{};  // 0x0000
public:
	C_ItemRenderer *renderer{};  // 0x0058
private:
	[[maybe_unused]] uint8_t pad_0x50[0x238]{};  // 0x60
public:
	C_BaseActorRenderContext(C_ScreenContext *ScreenCtx, C_ClientInstance *client, MinecraftGame *game);
};

class C_ItemRenderer {
public:
	void renderGuiItemNew(C_BaseActorRenderContext *BaseActorRenderCtx, C_ItemStack *item, int mode, float x, float y, float opacity, float scale, bool isEnchanted);
	void renderGuiItemInChunk(C_BaseActorRenderContext *BaseActorRenderCtx, C_ItemStack *item, float x, float y, float opacity, float scale, bool isEnchanted, int mode);
};

class C_Player;
class C_ItemStack;
class ItemDescriptor;
using PointingStruct = class Level;

class C_Item {
private:
	[[maybe_unused]] uint8_t pad_0008[0x70]{};  // 0x0008
public:
	int16_t maxStackSize{};  // 0x078
	int16_t itemId{};        // 0x07A
private:
	[[maybe_unused]] uint8_t pad_0094[4]{};  // 0x0094
public:
	TextHolder tileName{};  // 0x080
private:
	[[maybe_unused]] uint8_t pad_00B8[8]{};  // 0x00B8
public:
	TextHolder name{};  // 0x088
private:
	[[maybe_unused]] uint8_t pad_00E0[8]{};  // 0x00E0
public:
	TextHolder isFrom{};  // 0x00E8
private:
	[[maybe_unused]] uint8_t pad_0108[80]{};  // 0x0108
public:
	int16_t duration{};  // 0x0158

private:
	virtual void destructor();                                              //~C_Item()                                         // 0
	virtual bool initServer(class Json_Value &, class SemVersion const &);  // 1
	virtual void tearDown(void);                                            // 2
public:
	virtual int getMaxUseDuration(class ItemInstance const *);                                          // 3
	virtual int getMaxUseDuration(C_ItemStack const *) const;                                           // 4
	virtual bool isMusicDisk(void);                                                                     // 5
	virtual void executeEvent(class C_ItemStack &, std::u8string const &, class RenderParams &) const;  // 6
	virtual bool isComponentBased(void);                                                                // 7
	virtual bool isArmor(void);                                                                         // 8
	virtual bool isBlockPlanterItem(void);                                                              // 9
	virtual bool isBucket(void);                                                                        // 10
	virtual bool isCamera(void);                                                                        // 11
	virtual bool isCandle(void);                                                                        // 12
	virtual bool isDamageable(void);                                                                    // 13
	virtual bool isDyeable(void);                                                                       // 14
	virtual bool isDye(void);                                                                           // 15
	virtual MC_Color getItemColor(void);                                                                // 16
	virtual bool isFertilizer(void);                                                                    // 17
	virtual bool isFood(void);                                                                          // 18
	virtual bool isThrowable(void);                                                                     // 19
	virtual bool isUseable(void);                                                                       // 20
	virtual class ItemComponent *getComponent(TextHolder const &);                                      // 21
	virtual class ICameraItemComponent *getCamera(void);                                                // 22
	virtual class IFoodItemComponent *getFood(void);                                                    // 23
	virtual class FuelItemComponent const *getFuel(void);                                               // 24
	virtual C_Item *setMaxStackSize(unsigned char);                                                     // 25
	virtual C_Item *setStackedByData(bool);                                                             // 26
	virtual C_Item *setMaxDamage(int);                                                                  // 27
	virtual C_Item *setHandEquipped(void);                                                              // 28
	virtual C_Item *setUseAnimation(int);                                                               // 29
	virtual C_Item *setMaxUseDuration(int);                                                             // 30
	virtual C_Item *setRequiresWorldBuilder(bool);                                                      // 31
	virtual C_Item *setExplodable(bool);                                                                // 32
	virtual C_Item *setFireResistant(bool);                                                             // 33
	virtual C_Item *setIsGlint(bool);                                                                   // 34
	virtual C_Item *setShouldDespawn(bool);                                                             // 35
	virtual std::unique_ptr<CompoundTag> buildNetworkTag(void);                                         // We forgored these funcs, the vtable index numbers are now invalid
	virtual std::vector<std::u8string> initializeFromNetwork(CompoundTag const &);
	virtual class BlockShape getBlockShape(void);                                                                                                   // 36
	virtual bool canBeDepleted(void);                                                                                                               // 37
	virtual bool canDestroySpecial(C_Block const &);                                                                                                // 38
	virtual int getLevelDataForAuxValue(int);                                                                                                       // 39
	virtual bool isStackedByData(void);                                                                                                             // 40
	virtual short getMaxDamage(void);                                                                                                               // 41
	virtual int getAttackDamage(void);                                                                                                              // 42
	virtual bool isHandEquipped(void);                                                                                                              // 43
	virtual bool isGlint(C_ItemStack const &);                                                                                                      // 44
	virtual bool isPattern(void);                                                                                                                   // 45
	virtual int getPatternIndex(void);                                                                                                              // 46
	virtual void showsDurabilityInCreative(void);                                                                                                   // 47
	virtual bool isWearableThroughLootTable(CompoundTag const *);                                                                                   // 48
	virtual bool canDestroyInCreative(void);                                                                                                        // 49
	virtual bool isDestructive(int);                                                                                                                // 50
	virtual bool isLiquidClipItem(int);                                                                                                             // 51
	virtual bool shouldInteractionWithBlockBypassLiquid(C_Block const &);                                                                           // 52
	virtual bool requiresInteract(void);                                                                                                            // 53
	virtual void appendFormattedHovertext(C_ItemStack const &, Level &, std::u8string &, bool);                                                     // 54
	virtual bool isValidRepairItem();                                                                                                               // 55
	virtual int getEnchantSlot(void);                                                                                                               // 56
	virtual int getEnchantValue(void);                                                                                                              // 57
	virtual int getArmorValue(void);                                                                                                                // 58
	virtual bool isComplex(void);                                                                                                                   // 59
	virtual bool isValidAuxValue(int);                                                                                                              // 60
	virtual int getDamageChance(int);                                                                                                               // 61
	virtual float getViewDamping(void);                                                                                                             // 62
	virtual __int64 uniqueAuxValues(void);                                                                                                          // 63
	virtual bool isActorPlacerItem(void);                                                                                                           // 64
	virtual bool isMultiColorTinted(C_ItemStack const &);                                                                                           // 65
	virtual MC_Color getColor(CompoundTag const *, ItemDescriptor const &);                                                                         // 66
	virtual bool hasCustomColor(C_ItemStack const &);                                                                                               // 67
	virtual bool hasCustomColor(CompoundTag const *);                                                                                               // 68
	virtual void clearColor(C_ItemStack &);                                                                                                         // 69
	virtual void clearColor(CompoundTag *);                                                                                                         // 70
	virtual void setColor(C_ItemStack &, MC_Color const &);                                                                                         // 71
	virtual MC_Color getBaseColor(C_ItemStack const &);                                                                                             // 72
	virtual MC_Color getSecondaryColor(C_ItemStack const &);                                                                                        // 73
	virtual class ActorDefinitionIdentifier getActorIdentifier(C_ItemStack const &);                                                                // 74
	virtual __int64 saveAdditionalData(C_ItemStack const &, CompoundTag &);                                                                         // 75
	virtual __int64 readAdditionalData(C_ItemStack &, CompoundTag const &);                                                                         // 76
	virtual __int64 buildIdAux(short, CompoundTag const *);                                                                                         // 77
	virtual bool canUseOnSimTick(void);                                                                                                             // 78
	virtual C_ItemStack *use(C_ItemStack &, C_Player &);                                                                                            // 79
	virtual bool dispense(C_BlockSource &, class Container &, int, vec3_t const &, unsigned char);                                                  // 80
	virtual class ItemUseMethod useTimeDepleted(C_ItemStack &, Level *, C_Player *);                                                                // 81
	virtual void releaseUsing(C_ItemStack &, C_Player *, int);                                                                                      // 82
	virtual float getDestroySpeed(C_ItemStack const &, C_Block const &);                                                                            // 83
	virtual void hurtActor(C_ItemStack &, C_Entity &, C_Entity &);                                                                                  // 84
	virtual void hitActor(C_ItemStack &, C_Entity &, C_Entity &);                                                                                   // 85
	virtual void hitBlock(C_ItemStack &, C_Block const &, vec3_ti const &, C_Entity &);                                                             // 86
	virtual bool mineBlock(C_ItemStack &, C_Block const &, int, int, int, C_Entity *);                                                              // 87
	virtual bool mineBlock(C_ItemStack &, C_Block const &, int, int, int, C_Entity *) const;                                                        // 88
	virtual std::u8string buildDescriptionName(C_ItemStack const &);                                                                                // 89
	virtual std::u8string buildDescriptionId(ItemDescriptor const *, CompoundTag const *);                                                          // 90
	virtual std::u8string buildEffectDescriptionName(C_ItemStack const &);                                                                          // 91
	virtual std::u8string buildCategoryDescriptionName(void);                                                                                       // 92
	virtual void readUserData(C_ItemStack &, class IDataInput &, class ReadOnlyBinaryStream);                                                       // 93
	virtual void writeUserData(C_ItemStack const &, class IDataOutput &);                                                                           // 94
	virtual uint8_t getMaxStackSize(ItemDescriptor const *);                                                                                        // 95
	virtual bool inventoryTick(C_ItemStack &, Level &, C_Entity &, int, bool);                                                                      // 96
	virtual void refreshedInContainer(C_ItemStack const &, Level &);                                                                                // 97
	virtual class HashedString getCooldownType(void);                                                                                               // 98
	virtual int getCooldownTime(void);                                                                                                              // 99
	virtual void fixupCommon(C_ItemStack &);                                                                                                        // 100
	virtual void fixupCommon(C_ItemStack &, Level &);                                                                                               // 101
	virtual short getDamageValue(CompoundTag const *);                                                                                              // 102
	virtual void setDamageValue(C_ItemStack &, short);                                                                                              // 103
	virtual class InHandUpdateType getInHandUpdateType(C_Player const &, C_ItemStack const &, C_ItemStack const &, bool, bool);                     // 104
	virtual InHandUpdateType getInHandUpdateType(C_Player const &, C_ItemStack const &, C_ItemStack const &, bool, bool, __int64 fakeuseotherone);  // 105
	virtual bool validFishInteraction(int);                                                                                                         // 106
	virtual bool isSameItem(C_ItemStack const &, C_ItemStack const &);                                                                              // 107
	virtual void initClient(class Json_Value &, class SemVersion const &);                                                                          // 108
	virtual std::u8string getInteractText(C_Player const &);                                                                                        // 109
	virtual int getAnimationFrameFor(C_Entity *, bool, C_ItemStack const *, bool);                                                                  // 110
	virtual bool isEmissive(int);                                                                                                                   // 111
	virtual struct Brightness getLightEmission(int);                                                                                                // 112
	virtual struct TextureUVCoordinateSet getIcon(C_ItemStack const &, int, bool);                                                                  // 113
	virtual int getIconYOffset(void);                                                                                                               // 114
	virtual C_Item *setIcon(const std::u8string &, int);                                                                                            // 115
	virtual C_Item *setIcon();                                                                                                                      // 116
	virtual C_Item *setIconAtlas(const std::u8string &, int);                                                                                       // 117
	virtual bool canBeCharged(void);                                                                                                                // 118
	virtual void playSoundIncrementally(C_ItemStack const &, C_Entity &);                                                                           // 119
	virtual void playSoundIncrementally(C_ItemStack const &, C_Entity &) const;                                                                     // 120
	virtual float getFurnaceBurnIntervalMultipler(C_ItemStack const &);                                                                             // 121
	virtual float getFurnaceXPmultiplier(C_ItemStack const &);                                                                                      // 122
	virtual std::u8string getAuxValuesDescription(void);                                                                                            // 123
	virtual bool _checkUseOnPermissions(C_Entity &, C_ItemStack &, unsigned char const &, vec3_ti const &);                                         // 124
	virtual bool _calculatePlacePos(C_ItemStack &, C_Entity &, unsigned char &, vec3_ti &);                                                         // 125
	virtual bool _useOn(C_ItemStack &, C_Entity &, vec3_ti, unsigned char, float, float, float);                                                    // 126
	virtual __int64 getArmorKnockbackResistance(void);                                                                                              // 127

public:
	constexpr bool isTool() {
		switch (itemId) {
		case 299:  // 打火石
		case 391:  // 指南针
		case 422:  // 末影珍珠
		case 571:  // 海洋之心
		case 560:  // 龙息
		case 386:  // 纸
		case 568:  // 不死图腾
		case 512:  // 绿宝石
		case 304:  // 钻石
		case 306:  // 金锭
		case 548:  // 命名牌
		case 521:  // 附魔书
		case 570:  // 鹦鹉螺壳
		case 426:  // 药水
		case 561:  // 喷溅药水
		case 309:  // 锹
		case 313:
		case 323:
		case 296:
		case 317:
		case 605:
		case 310:  // 镐
		case 324:
		case 314:
		case 297:
		case 318:
		case 606:
		case 311:  // 斧
		case 315:
		case 325:
		case 298:
		case 319:
		case 607:
		case 421:  // 剪刀
			return true;
		default:
			return false;
		}
	}
	constexpr bool isWeapon() {
		switch (itemId) {
		case 308:  // 剑
		case 312:
		case 307:
		case 322:
		case 316:
		case 604:
		case 311:  // 斧
		case 315:
		case 325:
		case 298:
		case 319:
		case 607:
			return true;
		default:
			return false;
		}
	}
	constexpr bool isShooter() {
		switch (itemId) {
		case 300:  // 弓箭
		case 301:  // 箭矢
			return true;
		default:
			return false;
		}
	}
	constexpr bool isPickaxe() {
		switch (itemId) {
		case 310:  // 镐
		case 324:
		case 314:
		case 297:
		case 318:
		case 606:
			return true;
		default:
			return false;
		}
	}
	constexpr bool isShovel() {
		switch (itemId) {
		case 309:  // 锹
		case 313:
		case 323:
		case 296:
		case 317:
		case 605:
			return true;
		default:
			return false;
		}
	}

	constexpr bool isBlock(bool hive) {
		switch (itemId) {
		case 247:          // 下界反应核
		case -746:         // Forzen Boom Box
		case -747:         // Knockback Boom Box
		case -748:         // Poison Boom Box
		case -749:         // Boom Box
		case 30:           // 蜘蛛网
			return !hive;  // hive == true return false;
		default:
			const auto val = *reinterpret_cast<uintptr_t ***>(reinterpret_cast<uintptr_t>(this) + 0x1A0);
			return val != nullptr && *val != nullptr;
		}
	}
};

class ItemDescriptor {
private:
	[[maybe_unused]] uint8_t pad_0x0[0x48]{};  // 0x0000
public:
	ItemDescriptor() {
		fast_io::freestanding::my_memset(this, 0x0, sizeof(ItemDescriptor));
	}
	ItemDescriptor(int id, int16_t itemData);
};

class C_ItemData {
private:
	[[maybe_unused]] uint8_t pad_0x0[0x8]{};  // 0x00
public:
	uint16_t data{};  // 0x08
private:
	[[maybe_unused]] uint8_t pad_0x0A[0xB6]{};  // 0x0A
};

class C_ItemStack {
private:
	uintptr_t **vTable{};  // 0x0000
public:
	C_Item **item{};         // 0x08
	CompoundTag *tag{};      // 0x10
	C_ItemData *itemData{};  // 0x18 itemData Structure (blocks)
	uint16_t extraData{};    // 0x20 (items)
public:
	int8_t count{};  // 0x22
private:
	[[maybe_unused]] uint8_t pad_0x23[0x65]{};  // 0x23
	[[maybe_unused]] uint8_t idk_3{};           // 0x88
	[[maybe_unused]] uint8_t pad_0x89[0x7]{};   // 0x89
public:
	C_ItemStack() {
		fast_io::freestanding::my_memset(this, 0x0, sizeof(C_ItemStack));
	}

	C_ItemStack(C_BlockLegacy &legacy, int count) {
		fast_io::freestanding::my_memset(this, 0x0, sizeof(C_ItemStack));
		reinit(legacy, count);
	}

	C_ItemStack(C_Item &item, int count, int itemData) {
		fast_io::freestanding::my_memset(this, 0x0, sizeof(C_ItemStack));
		reinit(item, count, itemData);
	}

	C_ItemStack(Tag const &tag);

	void fromTag(Tag const &tag);

	void save(CompoundTag **tag);

	void setUserData(std::unique_ptr<Tag> tag);

	inline bool isValid() {
		return this->item != nullptr && *this->item != nullptr;
	}

	inline C_Item *getItem() {
		return *this->item;
	}

	void reinit(C_BlockLegacy &legacy, int count);

	void reinit(C_Item &item, int count, int itemData);

	int getEnchantValue(int enchantId);

	bool isEnchanted() {
		int enchantValue = 0;
		for (int i = 0; i < 40; i++) {
			enchantValue = this->getEnchantValue(i);
		}
		if (enchantValue != 0)
			return true;
		else
			return false;
	}

	float getArmorValueWithEnchants() {
		if (!this->item || !(*this->item)->isArmor())
			return 0;

		return (float)(((*this->item)->getArmorValue() + ((this->getEnchantValue(0) * 1.5f    // Protection
														   + this->getEnchantValue(5) * 0.4f  // Thorns
														   + this->getEnchantValue(3) * 0.4f  // Blast Protection
														   + this->getEnchantValue(1) * 0.4f  // Fire Protection
														   + this->getEnchantValue(4) * 0.4f  // Projectile Protection
														   ))));
	}

	float getAttackingDamageWithEnchants() {
		if (!this->item)
			return 0;
		int sharpnessValue = this->getEnchantValue(9);
		return (*this->item)->getAttackDamage() + 1.25f * sharpnessValue;
	}

	void setShowPickUp(bool b) {
		*(bool *)(reinterpret_cast<uintptr_t>(this) + 0x30) = b;
	}

	uint16_t getItemData() {
		if (itemData != nullptr) [[likely]]
			return itemData->data;  // this->itemData ?? ?? ?? ?? ?? ?? ?? ??, this->itemData + 0x1 XX XX(itemData) ?? ?? ?? ?? ?? ??
		return extraData;
	}

private:
	inline void setVtable();
};

class C_ArmorItem : public C_Item {
private:
	[[maybe_unused]] uint8_t pad_0x108[0x228 - sizeof(C_Item)]{};  // 0x100
public:
	int ArmorSlot{};  // 0x1B8

public:
	bool isHelmet() {
		return ArmorSlot == 0;
	}
	bool isChestplate() {
		return ArmorSlot == 1;
	}
	bool isLeggings() {
		return ArmorSlot == 2;
	}
	bool isBoots() {
		return ArmorSlot == 3;
	}
};

class ItemRegistry {
public:
	static C_Item ***getItemFromId(void *ptr, int itemId);
	static C_Item ***lookUpByName(void *, void *, TextHolder &);
};
